<?php
declare(strict_types=1);

namespace App\Services\Tools;


use App\Exceptions\BasicException;
use Exception;
use Ixudra\Curl\Facades\Curl;
use stdClass;

class ZeGoService
{
    protected $appId;
    protected $secret;
    protected $roomId;
    protected $userId;
    protected $signatureVersion;
    protected $ktvUrl = "https://ktv-api.zego.im";

    const SONGS_TOP_HOT = "8888";
    const SONGS_TOP_NET = "23784";
    const SONGS_TOP_DJ = "24971";
    const SONGS_TOP_NEW = "24971";

    public function __construct(int $roomId, int $userId, string $signatureVersion = "2.0")
    {
        $this->appId = env("ZEGO_APPID");
        $this->secret = env("ZEGO_SERVER_SECRET");
        $this->signatureVersion = $signatureVersion;
        $this->roomId = $roomId;
        $this->userId = $userId;
    }

    protected function sign(string $nonce, int $time): string
    {
        $str = $this->appId. $nonce . $this->secret . $time;
        return md5($str);
    }

    /**
     * @return array
     * @throws Exception
     */
    protected function params(string $action): array
    {
        $nonce = bin2hex(random_bytes(8));
        $time = time();
        return [
            "Action" => $action,
            "AppId" => (int)$this->appId,
            "Signature" => $this->sign($nonce, $time),
            "SignatureNonce" => $nonce,
            "SignatureVersion" => $this->signatureVersion,
            "Timestamp" => $time,
            "UserId" => (string)$this->userId,
            "RoomId" => (string)$this->roomId,
        ];
    }

    /**
     * @throws Exception
     */
    public function getSongsTop(string $keyword = "", int $page = 1): array
    {
        if(!empty($keyword)){
            return $this->searchSongs($keyword, $page);
        }
        $action = "DescribeTopSongs";
        $params = $this->params($action);
        $params["TopId"] = self::SONGS_TOP_HOT;
        $params["Page"] = $page;

        $curl = new \Ixudra\Curl\CurlService();
        $res = $curl->to($this->ktvUrl . "/")->withData($params)->get();
        return $this->songsResponse($res);
    }

    /**
     * @param string $keywords
     * @param int $page
     * @return array
     * @throws Exception
     */
    public function searchSongs(string $keywords = "", int $page = 1): array
    {
        $action = "QuerySong";
        $params = $this->params($action);
        $params["Keyword"] = $keywords;
        $params["Page"] = $page;

        $curl = new \Ixudra\Curl\CurlService();
        $res = $curl->to($this->ktvUrl . "/")->withData($params)->get();
        return $this->songsResponse($res);
    }

    public function songsResponse(string $res): array
    {
        $res = json_decode($res, true);
        if($res["Code"] != 0){
            $message = $res["Message"] ?: "获取歌曲失败";
            throw new BasicException(-1, $message);
        }
        if(empty($res["Data"]["Songs"])){
            throw new BasicException(-1, "暂无歌曲");
        }

        $response = [];
        foreach ($res["Data"]["Songs"] as $song){
            $response[] = [
                "SongId" => $song["SongId"],
                "SongName" => $song["SongName"],
                "SingerName" => $song["SingerName"],
                "Copyright" => $song["Copyright"]["Channel"]
            ];
        }

        return $response;
    }
}